package com.sunxd.znginxdemo2.Demo;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.sunxd.znginxdemo2.Demo.annotation.LimitHandlerAnnotation;
import com.sunxd.znginxdemo2.Demo.content.BaseContent;
import com.sunxd.znginxdemo2.Demo.limit.AbstractLimitStrategy;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * Description: 加载并排序
 */
@Component
@Slf4j
public class LimitDelegate1 implements ApplicationContextAware {

    private AbstractLimitStrategy limitStrategy;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        Map<String, Object> beansWithAnnotation = applicationContext.getBeansWithAnnotation(LimitHandlerAnnotation.class);
        List<AbstractLimitStrategy> list = Lists.newArrayList();
        for (Object bean : beansWithAnnotation.values()) {
            if (bean instanceof AbstractLimitStrategy) {
                LimitHandlerAnnotation limitHandler = bean.getClass().getAnnotation(LimitHandlerAnnotation.class);
                if (limitHandler instanceof AbstractLimitStrategy) {
                    list.add((AbstractLimitStrategy) limitHandler);
                }
            }
        }
        list.sort(Comparator.comparing(this::findOrder));
        int size = list.size();
        for (int i = 0; i < size; i++) {
            if(Objects.equals(i ,size-1)){
                list.get(i).setNextHandler(null);
            }else {
                list.get(i).setNextHandler(list.get(i+1));
            }
        }
        limitStrategy = list.get(0);
    }
    /**
     * 限制校验
     * @return
     */
    public Boolean doExecute(BaseContent baseContent) {
        limitStrategy.doCheck(baseContent);
        return Boolean.TRUE;
    }
    protected Integer findOrder(Object obj) {
        Order order = obj.getClass().getAnnotation(Order.class);
        return Objects.isNull(order) ? Integer.MAX_VALUE : order.value();
    }

}
